package com.cjj.refresh;

import ohos.agp.animation.*;
import ohos.agp.components.*;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;

/**
 * BeautifulRefreshLayout Created by cjj on 2015/8/4.
 *
 * @author hw
 * @since 2021/7/20
 */
public class BeautifulRefreshLayout extends RefreshLayout {
    private float waveHeight = 200;
    private float headHeight = 120;
    private EventHandler eventHandler = new EventHandler(EventRunner.getMainEventRunner());
    private AnimatorGroup animatorGroup;
    private AnimatorValue animatorValue1;
    private AnimatorValue animatorValue2;
    private AnimatorValue animatorValue3;
    private AnimatorValue animatorValue4;

    public BeautifulRefreshLayout(Context context) {
        this(context, null, null);
    }

    public BeautifulRefreshLayout(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    public BeautifulRefreshLayout(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs);
    }

    /**
     * 初始化
     *
     * @param attrs attr
     */
    private void init(AttrSet attrs) {
        // 初始化headView
        final Component headView = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_view_head,
                null, false);
        final WaveView waveView = (WaveView) headView.findComponentById(ResourceTable.Id_draweeView);
        final Text tvTip = (Text) headView.findComponentById(ResourceTable.Id_tv_tip);
        final RippleView rippleView = (RippleView) headView.findComponentById(ResourceTable.Id_ripple);
        final RainView rain = (RainView) headView.findComponentById(ResourceTable.Id_rain);
        rain.setVisibility(Component.HIDE);
        rippleView.setRippleListener(() -> {
            if (listener != null) {
                listener.onRefresh(BeautifulRefreshLayout.this);
            }
        });

        // 初始化waveView
        initWaveView(waveView, tvTip);

        // 设置headView的高度
        setHeaderHeight(DensityUtil.vp2px(getContext(), headHeight));

        // 设置headView
        setHeaderView(headView);

        initAnimatorForPull(waveView);

        // 松开后的监听
        setPullToRefreshListener(refreshLayout -> {
            tvTip.setText("下雨中...");
            rain.setVisibility(Component.VISIBLE);
            rain.startRain();
            waveView.setHeadHeight(DensityUtil.vp2px(BeautifulRefreshLayout.this.getContext(), headHeight));
            animatorGroup.start();
            eventHandler.postTask(() -> {
                rippleView.startReveal();
                rain.stopRain();
            }, 3000);
        });
    }

    private void initWaveView(WaveView waveView, Text tv_tip) {
        // 设置波浪的高度
        setWaveHeight(DensityUtil.vp2px(getContext(), waveHeight));
        // 监听波浪变化监听
        setPullWaveListener(new PullWaveListener() {
            @Override
            public void onPulling(RefreshLayout refreshLayout, float fraction) {
                float headW = DensityUtil.vp2px(getContext(), waveHeight);
                waveView.setHeadHeight((int) (DensityUtil.vp2px(getContext(),
                        headHeight) * limitValue(1, fraction)));
                waveView.setWaveHeight((int) (headW * Math.max(0, (double) fraction - 1)));
                waveView.invalidate();
                if (DensityUtil.vp2px(getContext(), headHeight) > (int) (DensityUtil.vp2px(getContext(),
                        headHeight) * limitValue(1, fraction))) {
                    tv_tip.setText("下拉下雨");
                } else {
                    tv_tip.setText("松开下雨");
                }
            }

            @Override
            public void onPullReleasing(RefreshLayout refreshLayout, float fraction) {
            }
        });
    }

    private void initAnimatorForPull(WaveView waveView) {
        animatorGroup = new AnimatorGroup();
        animatorValue1 = new AnimatorValue();
        animatorValue1.setDuration(250);
        animatorValue1.setValueUpdateListener((animatorValue, animatedValue) -> {
            waveView.setWaveHeight((int) ((double) animatedValue * -300));
            waveView.invalidate();
        });
        animatorValue2 = new AnimatorValue();
        animatorValue2.setDuration(250);
        animatorValue2.setCurveType(Animator.CurveType.BOUNCE);
        animatorValue2.setValueUpdateListener((animatorValue, animatedValue) -> {
            waveView.setWaveHeight((int) ((1 - (double) animatedValue) * -300));
            waveView.invalidate();
        });
        animatorValue3 = new AnimatorValue();
        animatorValue3.setDuration(200);
        animatorValue3.setValueUpdateListener((animatorValue, animatedValue) -> {
            waveView.setWaveHeight((int) ((double) animatedValue * -100));
            waveView.invalidate();
        });
        animatorValue4 = new AnimatorValue();
        animatorValue4.setDuration(125);
        animatorValue4.setValueUpdateListener((animatorValue, animatedValue) -> {
            waveView.setWaveHeight((int) ((1 - (double) animatedValue) * -100));
            waveView.invalidate();
        });
        // 4个动画按顺序播放
        animatorGroup.runSerially(animatorValue1, animatorValue2, animatorValue3,
                animatorValue4);
    }

    /**
     * 限定值
     *
     * @param aValue a
     * @param bValue bValue
     * @return limitValue
     */
    public float limitValue(float aValue, float bValue) {
        float valve = 0;
        final float min = Math.min(aValue, bValue);
        final float max = Math.max(aValue, bValue);
        valve = valve > min ? valve : min;
        valve = valve < max ? valve : max;
        return valve;
    }

    /**
     * BuautifulRefreshListener
     */
    public interface BuautifulRefreshListener {
        void onRefresh(BeautifulRefreshLayout refreshLayout);
    }

    private BuautifulRefreshListener listener;

    /**
     * setBuautifulRefreshListener
     *
     * @param listener BuautifulRefreshListener
     */
    public void setBuautifulRefreshListener(BuautifulRefreshListener listener) {
        this.listener = listener;
    }
}
